package com.example.demo.service.impl;

import com.example.demo.constant.RedisConstant;
import com.example.demo.constant.SystemConstant;
import com.example.demo.dto.CommodityDTO;
import com.example.demo.exception.CommodityNotFoundException;
import com.example.demo.exception.StockDeductionException;
import com.example.demo.exception.ZeroStockException;
import com.example.demo.mapper.StudentClothingMapper;
import com.example.demo.mapper.StudentCouponsMapper;
import com.example.demo.mapper.StudentPointsMapper;
import com.example.demo.mapper.entity.*;
import com.example.demo.service.StudentPointsService;
import com.example.demo.utils.CouponsUtil;
import com.example.demo.utils.PageBo;
import com.example.demo.utils.PageVo;
import com.example.demo.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Lucy
 * @create 2024-02-13 16:04
 */
@Service
public class StudentPointsServiceImpl implements StudentPointsService {

    @Autowired
    private StudentPointsMapper mapper;

    @Autowired
    private StudentClothingMapper clothingMapper;

    @Autowired
    private StudentCouponsMapper couponsMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public void insertStudentPoints(StudentPoints points) {
        mapper.insertStudentPoints(points);
    }

    @Override
    public StudentPoints selectStudentPointsByStudentId(int studentId) {
        return mapper.selectStudentPointsByStudentId(studentId);
    }

    @Override
    public PageVo<CommodityDTO> getCommoditiesList(PageBo pageBo, int type) {
        List<Commodity> commoditiesList = mapper.selectTypeCommodityList(type);
        List<CommodityDTO> commoditiesDTOList = new ArrayList<>();
        for (Commodity commodity : commoditiesList) {
            CommodityDTO dto = new CommodityDTO();
            dto.setCommodityId(commodity.getCommodityId());
            dto.setPointsRequired(commodity.getPointsRequired());
            dto.setCommodityName(commodity.getCommodityName());
            dto.setImageUrl(SystemConstant.aliyunOSSUrlPrefix + commodity.getImageUrl());
            commoditiesDTOList.add(dto);
        }
        return new PageVo<>(pageBo, commoditiesDTOList);
    }

    @Override
    public PageVo<CommodityDTO> getCommoditiesList(PageBo pageBo, int type, int gender) {
        List<Commodity> commoditiesList = mapper.selectTypeCommodityList(type);
        List<CommodityDTO> commoditiesDTOList = new ArrayList<>();
        for (Commodity commodity : commoditiesList) {
            Clothing clothing = clothingMapper.selectClothingById(commodity.getClothingId());
            if (clothing.getGender() != gender) {
                continue;
            }
            CommodityDTO dto = new CommodityDTO();
            dto.setCommodityId(commodity.getCommodityId());
            dto.setPointsRequired(commodity.getPointsRequired());
            dto.setCommodityName(commodity.getCommodityName());
            dto.setImageUrl(SystemConstant.aliyunOSSUrlPrefix + commodity.getImageUrl());
            commoditiesDTOList.add(dto);
        }
        return new PageVo<>(pageBo, commoditiesDTOList);
    }

    @Override
    public PageVo<CommodityDTO> getCouponsList(PageBo pageBo, int type) {
        List<Commodity> commoditiesList = mapper.selectTypeCommodityList(type);
        List<CommodityDTO> commoditiesDTOList = new ArrayList<>();
        for (Commodity commodity : commoditiesList) {
            CommodityDTO dto = new CommodityDTO();
            dto.setCommodityId(commodity.getCommodityId());
            dto.setPointsRequired(commodity.getPointsRequired());
            dto.setCommodityName(commodity.getCommodityName());
            Coupons coupons = couponsMapper.selectCouponsById(commodity.getCouponsId());
            String imageUrl = CouponsUtil.generateCouponLabel(coupons);
            dto.setImageUrl(imageUrl);

            commoditiesDTOList.add(dto);
        }
        return new PageVo<>(pageBo, commoditiesDTOList);
    }

    @Override
    public Commodity selectCommodityById(int commodityId) {
        return mapper.selectCommodityById(commodityId);
    }

    @Override
    public void updateCommodityStock(Commodity commodity) throws StockDeductionException, ZeroStockException, CommodityNotFoundException {
        int retries = 3; // 设置重试次数
        while (retries > 0) {
            retries--;
            while (retries > 0) {
                retries--;
                if (commodity != null) {
                    if (commodity.getStock() > 0) {
                        int currentVersion = commodity.getVersion(); // 获取当前版本号
                        int updatedRows = mapper.deductStock(commodity.getCommodityId(), currentVersion); // 尝试更新并返回受影响的行数
                        if (updatedRows > 0) {
                            return; // 更新成功
                        } else {
                            commodity = mapper.selectCommodityById(commodity.getCommodityId()); // 获取最新商品信息
                        }
                    } else {
                        mapper.updateIsOffline(commodity.getCommodityId());
                        throw new ZeroStockException("商品缺货");
                    }
                } else {
                    throw new CommodityNotFoundException("商品不存在");
                }
            }
            throw new StockDeductionException("库存更新失败");
        }
    }

    @Override
    public void updateStudentPoints(int studentId, int earnedPoints, int spentPoints) {
        StudentPoints studentPoints = mapper.selectStudentPointsByStudentId(studentId);
        // 更新总积分和总消费积分
        studentPoints.setPoints(studentPoints.getPoints() + earnedPoints - spentPoints);
        studentPoints.setTotalEarned(studentPoints.getTotalEarned() + earnedPoints);
        studentPoints.setTotalSpent(studentPoints.getTotalSpent() + spentPoints);
        // 更新最后更新时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime lastUpdatedTime = LocalDateTime.now();
        String format = lastUpdatedTime.format(formatter);
        studentPoints.setLastUpdated(format);
        // 执行更新操作
        mapper.updateStudentPoints(studentPoints);
        redisUtil.addOrUpdate(RedisConstant.Student_Points_Rank_Name,studentId,studentPoints.getTotalEarned());
    }

    @Override
    public void insertExchangeRecord(ExchangeRecord exchangeRecord) {
        mapper.insertExchangeRecord(exchangeRecord);
    }

    @Override
    public List<StudentPoints> selectStudentPointsList() {
        return mapper.selectStudentPointsList();
    }
}
